#include <sys/epoll.h>
#include <functional>
#include <chrono>
#include <set>
#include <memory>
#include <iostream>

using namespace std;
// using namespace std::chrono;

struct TimerNodeBase
{
    time_t expire;
    int64_t id;
};

struct TimerNode : TimerNodeBase
{
    using Callback = std::function<void(const TimerNode &node)>;
    Callback func;
};

bool operator<(const TimerNodeBase &lhd, const TimerNodeBase &rhd)
{
    if (lhd.expire < rhd.expire)
        return true;
    else if (lhd.expire > rhd.expire)
        return false;
    return lhd.id < rhd.id;
}

class Timer
{
public:
    /*
    获取系统启动到现在的时间，单位ms
    */
    static time_t GetTick()
    {
        auto sc = chrono::time_point_cast<chrono::milliseconds>(chrono::steady_clock::now());
        auto tmp = chrono::duration_cast<chrono::milliseconds>(sc.time_since_epoch());
        return tmp.count();
    }

    static int64_t GenID()
    {
        return ++gid;
    }

    TimerNodeBase AddTimer(time_t msec, TimerNode::Callback func)
    {
        TimerNode tnode;
        tnode.expire = GetTick() + msec;
        tnode.func = func;
        tnode.id = GenID();

        timermap.insert(tnode);
        return static_cast<TimerNodeBase>(tnode);
    }

    bool DelTimer(TimerNodeBase &node)
    {
        auto iter = timermap.find(node); // C++14新特性
        if (iter != timermap.end())
        {
            timermap.erase(iter);
            return true;
        }
        return false;
    }

    bool CheckTimer()
    {
        auto iter = timermap.begin();
        if (iter != timermap.end() && iter->expire <= GetTick())
        {
            iter->func(*iter);
            timermap.erase(iter);
            return true;
        }
        return false;
    }

    time_t TimeToSleep()
    {
        // 先找到最小的节点
        auto iter = timermap.begin();
        if (iter == timermap.end())
        {
            return -1;
        }
        time_t diss = iter->expire - GetTick();
        return diss > 0 ? diss : 0;
    }

private:
    static int64_t gid;
    set<TimerNode, std::less<>> timermap; // std::less，这是默认的比较函数，它会调用元素类型的 < 运算符
};
int64_t Timer::gid = 0;

int main()
{
    int epfd = epoll_create(1);

    unique_ptr<Timer> timer = make_unique<Timer>();

    int i = 0;
    timer->AddTimer(1000, [&](const TimerNode &node)
                    { cout << Timer::GetTick() << " node id: " << node.id << " revoked times: " << ++i << endl; });
    timer->AddTimer(1000, [&](const TimerNode &node)
                    { cout << Timer::GetTick() << " node id: " << node.id << " revoked times: " << ++i << endl; });
    timer->AddTimer(3000, [&](const TimerNode &node)
                    { cout << Timer::GetTick() << " node id: " << node.id << " revoked times: " << ++i << endl; });

    auto node = timer->AddTimer(2100, [&](const TimerNode &node)
                                { cout << Timer::GetTick() << " node id: " << node.id << " revoked times: " << ++i << endl; });
    timer->DelTimer(node);

    cout << "now time: " << Timer::GetTick() << endl;

    epoll_event ev[64] = {0};

    while (true)
    {
        /*
        timeout 最近触发的定时任务离当前的时间;
        -1 永久阻塞
        */
        int n = epoll_wait(epfd, ev, 64, timer->TimeToSleep());
        for (int i = 0; i < n; i++)
        {
            /* 网络处理 */
        }
        /* 处理定时事件 */
        while (timer->CheckTimer())
            ;
    }

    return 0;
}